#include "common.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include "util-files.h"
#include "stru_queue.h"
#include "pcie_proce.h"

void log_statis_width(char *para, int threadId) {
    // printf("带宽日志记录 \n");
    int logfd;
    char logPath[100];
    sprintf(&logPath, "/home/han/linux_cpu/log/log_statis_width_%d.log", threadId);
    if(!logfd) {
        logfd = open(&logPath, O_RDWR|O_APPEND |O_CREAT, 00777);
    }
    write(logfd, para, strlen(para));
    close(logfd);
}

/***
 * @param sPathName 创建多个层级的目录
 */ 
int CreateDir(const char *sPathName) {  
    char DirName[256];  
    strcpy(DirName, sPathName);  
    int i,len = strlen(DirName);
    for(i=1; i<len; i++)  
    {  
        if(DirName[i]=='/')  
        {  
            DirName[i] = 0; 
            if(access(DirName, NULL)!=0)  
            {  
                if(mkdir(DirName, 0755)==-1)  
                {   
                    LOG_ERROR("#ERR: error to create directory, directory is %s \n", sPathName);   
                    return KT_ERROR;   
                }  
            }  
            DirName[i] = '/';  
        }  
    }  
    return KT_OK;  
}

/**
 * @param cfile 关闭当前文件,上报信息,并初始化为初始状态
 */
int file_close(FilePro *cfile) {
    int ret = close(cfile->fd);         //关闭文件
    /** 文件信息上报 */
    cfile->finfo.file_size = FLOAT_ACCURACY(cfile->fsize, SIZE_MB);  //将B字节转化为MB字节, 精度为0.1
    //#note: 文件上报 
    sendToMsg(&cfile->finfo, INFO_FILE);
    LOG_DEBUG("文件上报: %lfMB, filesize: %ldB \n", cfile->finfo.file_size, cfile->fsize);
    memset((void *)cfile, 0x0, sizeof(FilePro));
}


/***
 * @param fname 生成文件名
 * @param directory 文件目录
 * @param queue 队列参数
 */ 
int set_fname(FilePro *cfile, PackWriteFile *pwf, BQueue *queue) {
    time_t timep;
    time(&timep);
    struct tm *tm = localtime(&timep);

    struct timeval tv; 
    gettimeofday(&tv,NULL); //获取当前时间微妙
   
    if(NULL == tm) {
        LOG_ERROR("#ERR: -set_fname- error to get localtim \n");
        return KT_ERROR;
    }
    RecvCmd *recv_cmd = pwf->recv_cmd; 
    cfile->finfo.file_type = getRthFileTypeByChannel(queue->channel);        //文件类型
    cfile->finfo.sec =  tm->tm_sec;
    cfile->finfo.min =  recv_cmd->min;
    cfile->finfo.hour =  recv_cmd->hour;
    cfile->finfo.date =  recv_cmd->date;
    cfile->finfo.month =  recv_cmd->month;
    cfile->finfo.year =  recv_cmd->year;
    cfile->finfo.task_num = pwf->recv_cmd->Tasknum;
    cfile->finfo.type = ETH_TYPE_FILEL;         //协议类型
    cfile->finfo.head = ETH_HEAD;               //协议头部
    cfile->finfo.tail = sizeof(FileInfo); 

    char *cval[10] = {"HCC","DBF","KGR","KZC","SIM","TARGET","CTRL","MONIT","GUID","MBSB"};
    sprintf(cfile->finfo.fname, "%04d_%s_%02d_%04d%02d%02d_%02d%02d%02d.dat", 
        cfile->finfo.task_num, cval[cfile->finfo.file_type], queue->channel,                       //文件名 任务代号, 数据源标号, 光纤编号
        cfile->finfo.year, cfile->finfo.month, cfile->finfo.date,                //任务名
        cfile->finfo.hour, cfile->finfo.min, cfile->finfo.sec                    //文件名 
    );
    sprintf(cfile->finfo.fpwd, "/%s%s", (pwf->directory+strlen(SAVE_PATH)), cfile->finfo.fname);

    sprintf(cfile->fpname, "%s%s", pwf->directory, cfile->finfo.fname);
    return KT_OK;
}

/**
 * @des Writes data from the queue to a file
 * @param cfile The object to write to the current file
 * @param pwf Some other parameters
 * @param queue Save buff 
 * @param rdata The data to be written to the file
 * @param rlen rdata`s len
 */
int save_tofile_with_queue(FilePro *cfile, PackWriteFile *pwf, BQueue *queue, uint8 *rdata, uint64 rlen) {
    if(cfile->flag == ISEXIST_NO) {   //如果为0的时候, 则创建文件
        set_fname(cfile, pwf, queue);
#ifndef  TEST_PICE_TO_CPU
        cfile->fd = open(cfile->fpname, O_RDWR |O_CREAT, 00777);
#endif
        if(cfile->fd == OPEN_FILE_ERROR) {
            LOG_ERROR("文件打开失败: fd: %d, fname: %s \n", cfile->fd, cfile->fpname);
            return KT_ERROR;
        }
        cfile->flag = ISEXIST_YES;       
        LOG_DEBUG("threadId: %d, cfile: %p, cfile.flag: %d,  fname: %s, fd: %d, \n", 
            pwf->threadId, cfile, cfile->flag, cfile->fpname, cfile->fd);
    }
#ifndef  TEST_PICE_TO_CPU
    //文件分片
    // pwf->fileLimitSize = 2;   //用于测试固定的内存分页
    unsigned long file_size = pwf->fileLimitSize * SIZE_GB;   
    long dif_size = (cfile->fsize + rlen) - file_size;
    if(dif_size > 0 && pwf->fileLimitSize != 0) {
        save_tofile_with_queue(cfile, pwf, queue, rdata, dif_size);
        save_tofile_with_queue(cfile, pwf, queue, rdata + dif_size, rlen - dif_size);
    }else {
        //写数据
        if(WRITE_FILE_ERROR == write(cfile->fd, rdata, rlen)) {
            LOG_ERROR("##ERR: err to write file: %s, fd: %d, queue: %p, channel: %d \n",
                cfile->fpname, cfile->fd, queue, queue->channel);
            exit(0);
        }else {
            cfile->fsize += rlen;     //记录每个文件的大小
            pwf->totalBytes += rlen;    //记录每个
            pwf->totalVlanBytes += queue->type == QU_VALN ? rlen : 0;
            pwf->totalPcieBytes += queue->type == QU_OPTI ? rlen : 0;
        }

        if(cfile->fsize == file_size && pwf->fileLimitSize != 0) {
            //如果满足条件, 则关闭文件, 重新打开文件
            file_close(cfile);             
        }
    }
#endif
#ifdef  LOCAL_WITH
    //每隔30s记录一次
    if(cfile->fsize % (2 * SIZE_GB) == 0) {
        time_t timep;
        time(&timep);
        struct tm *tm = localtime(&timep);
        char para[50];
        sprintf(&para, "%02d:%02d:%02d,%lf\n", 
        tm->tm_hour, tm->tm_min, tm->tm_sec,FLOAT_ACCURACY(cfile->fsize, SIZE_MB));
        log_statis_width(&para, pwf->threadId);
    }
#endif
    return KT_OK;
}



void testWriteFile() {
    uint8 buff[30];

    int fd = open("/mnt/cephfs/data/test.txt", O_RDWR |O_CREAT, 00777);
    LOG_DEBUG("fd %d\n", fd);

    if(fd < 0) {
        return;
    }

    write(fd, buff, 30);
}
